#include <REGX52.H>
#include "uart.c"
#include "timer.c"
#include "game.c"

void process_start()
{
    display_init();
    display_start_pic();
    // 等待开始按键按下，之后切换状态到速度选择
    while (game_pressed_button() != PRESSED_START)
    {
        /* code */
    }

    game_status = STATUS_SPEED_SELECT;
    // 更新游戏种子，增加随机性
    update_timer_seed();
}

void process_speed_select()
{
    unsigned char pressed;
    display_speed_select_page();
    do
    {
        pressed = game_pressed_button();
        switch (pressed)
        {
        case PRESSED_LEFT:
            if (game_speed == 0)
            {
                game_speed = 9;
            }
            else
            {
                game_speed--;
            }
            display_speed_select_num(game_speed);
            break;
        case PRESSED_RIGHT:
            if (game_speed == 9)
            {
                game_speed = 0;
            }
            else
            {
                game_speed++;
            }
            display_speed_select_num(game_speed);
            break;
        default:
            break;
        }
    } while (pressed != PRESSED_START);
    printf("game_status changed\n");
    // 代码执行到这个位置
    game_status = STATUS_PALYING;
}

/**
 *
 */
void process_playing()
{
    unsigned char pressed;
    game_zone_init();
    game_init_shape();
    display_game_playing_page();
    // 开中断，刷新游戏区域
    timer0_ISR_enable();
    while (game_status == STATUS_PALYING)
    {
        pressed = game_pressed_button();
        switch (pressed)
        {
        case PRESSED_LEFT:
            if (game_shape.x == 0)
            {
                break;
            }

            // 避免进入中断显示错误的画面
            timer0_ISR_disable();
            game_zone_remove_shape();
            // 左侧可以移动
            if (game_check_shape_placed(game_shape.x - 1, game_shape.y, game_shape.shape))
            {
                game_shape.x--;
            }
            game_zone_add_shape();
            game_zone_display();
            timer0_ISR_enable();
            break;
        case PRESSED_RIGHT:
            if (game_shape.x == 9)
            {
                break;
            }

            // 避免进入中断显示错误的画面
            timer0_ISR_disable();
            game_zone_remove_shape();
            // 左侧可以移动
            if (game_check_shape_placed(game_shape.x + 1, game_shape.y, game_shape.shape))
            {
                game_shape.x++;
            }
            game_zone_add_shape();
            game_zone_display();
            timer0_ISR_enable();
            break;
        case PRESSED_UP:
            timer0_ISR_disable();
            game_zone_remove_shape();
            if (game_check_shape_placed(game_shape.x, game_shape.y,
                                        TETRIS_SHAPES[game_shape.shape_type][(game_shape.shape_pos + 1) % 4]))
            {
                game_shape.shape_pos = (game_shape.shape_pos + 1) % 4;
                game_shape.shape = TETRIS_SHAPES[game_shape.shape_type][game_shape.shape_pos];
            }
            game_zone_add_shape();
            game_zone_display();
            timer0_ISR_enable();
            break;
        case PRESSED_DOWN:
            timer0_ISR_disable();
            game_zone_remove_shape();
            while (game_check_shape_placed(game_shape.x, game_shape.y + 1, game_shape.shape))
            {
                game_shape.y++;
            }
            game_zone_add_shape();
            game_zone_display();
            timer0_ISR_enable();
            break;
        case PRESSED_PAUSE:
            timer0_ISR_disable();
            display_pause();
            while (game_pressed_button() != PRESSED_PAUSE)
            {
            }
            display_pause_hide();
            timer0_ISR_enable();
            break;
        default:
            break;
        }
    }
}

unsigned char process_eliminate_lines()
{
    unsigned char i, j;
    unsigned char lines = 0;
    // 遍历game_zone数组，看一行是否都是1
    for (i = 0; i < 16; i++)
    {
        // 需要消除的行， 0011 1111 1111 1100
        if ((GAME_ZONE[i] & 0x3FFC) == 0x3FFC)
        {
            // 依次把上一行挪下来
            for (j = i; j > 0; j--)
            {
                GAME_ZONE[j] = GAME_ZONE[j - 1];
            }
            GAME_ZONE[0] = 0x2004;
            // 没有判断的一行挪下来了，当前行重新进行判断
            i--;

            game_score++;
            game_eliminated_lines++;
            lines++;
            if (game_speed < 9 && game_eliminated_lines % 10 == 0)
            {
                game_speed++;
            }
        }
    }
    return lines;
}

void process_game_over()
{
    display_game_over();
    while (game_pressed_button() != PRESSED_START)
    {
        /* code */
    }

    game_status = STATUS_START;
}

/**
 * 实现画面的更新，把游戏区的内容更新到屏幕上
 */
void timer0_ISR() interrupt 1
{
    if (game_status != STATUS_PALYING)
    {
        return;
    }
    if (game_frame_count < GAME_FRAME_TOTAL)
    {
        game_frame_count += (game_speed + 1);
    }
    else
    {
        game_frame_count = 0;
        // 方块下降
        // 当下方没有方块的时候，才能下降
        game_zone_remove_shape();
        if (game_check_shape_placed(game_shape.x, game_shape.y + 1, game_shape.shape))
        {
            game_shape.y++;
        }
        else
        {
            // 旧的先加入到游戏区
            game_zone_add_shape();
            // 方块消除
            if (process_eliminate_lines() > 0)
            {
                display_game_score();
                display_game_speed();
            }
            // 方块固定，产生一个新的方块
            next_game_shape();
            display_next_shape();
            // 新的方块能不能出现在游戏区，不能出现，则游戏结束
            if (!game_check_shape_placed(game_shape.x, game_shape.y, game_shape.shape))
            {
                game_status = STATUS_GAME_OVER;
            }
        }

        game_zone_add_shape();
        game_zone_display();
    }
}

void main()
{
    uart_init();
    display_init();
    timer0_init();
    // process_speed_select();
    while (1)
    {
        switch (game_status)
        {
        case STATUS_START:
            process_start();
            break;
        case STATUS_SPEED_SELECT:
            process_speed_select();
            break;
        case STATUS_PALYING:
            process_playing();
            break;
        case STATUS_GAME_OVER:
            process_game_over();
            break;
        default:
            break;
        }
    }
}